package com.mvc4g.example.shareModel.client.action;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.google.gwt.event.shared.HandlerRegistration;
import com.mvc4g.client.ActionInterface;
import com.mvc4g.client.Controller;
import com.mvc4g.example.shareModel.client.Constants;
import com.mvc4g.example.shareModel.client.bean.BeanB;
import com.mvc4g.example.shareModel.client.util.HasModelLoadHandler;
import com.mvc4g.example.shareModel.client.util.ModelLoadEvent;
import com.mvc4g.example.shareModel.client.util.ModelLoadHandler;
import com.mvc4g.example.shareModel.client.view.templates.RootTemplate;
import com.mvc4g.example.shareModel.client.view.views.ViewB;

public class ShowBAction implements ActionInterface, Constants {

	private Map<String, String> viewNameMap = new HashMap<String, String>();
	private Map<String, HandlerRegistration> handlerRegistrationMap = new HashMap<String, HandlerRegistration>();

	public ShowBAction() {

		viewNameMap.put(MODEL_A, VIEW_A);
		viewNameMap.put(MODEL_C, VIEW_C);

	}

	@Override
	public void execute(final Controller controller, Object form) {
		BeanB modelB = new BeanB();
		modelB.setInfo("B needs information from B");

		final ViewB viewB = (ViewB) controller.getView(VIEW_B);
		viewB.setModelB(modelB);

		boolean isAllModelLoaded = true;
		Iterator<String> it = viewNameMap.keySet().iterator();
		
		while (it.hasNext()) {
			isAllModelLoaded = setModel(viewB, controller, it.next()) && isAllModelLoaded;
		}

		if (isAllModelLoaded) {
			displayWidgetB(viewB, controller);
		}

	}

	@SuppressWarnings("unchecked")
	private boolean setModel(ViewB viewB, Controller controller,
			String modelName) {

		boolean loaded = false;

		HasModelLoadHandler<Object> view = (HasModelLoadHandler<Object>) controller
				.getView(viewNameMap.get(modelName));
		Object model = view.getModel();
		if (model == null) {
			if (!handlerRegistrationMap.containsKey(modelName)) {
				B_ModelLoadHandler handler = new B_ModelLoadHandler(viewB,
						controller, modelName);
				handlerRegistrationMap.put(modelName, view
						.addModelLoadHandler(handler));
			}
		} else {
			loaded = true;
			viewB.setModel(modelName, model);
		}

		return loaded;
	}

	private void displayWidgetB(ViewB viewB, Controller controller) {

		boolean isAllModelLoaded = true;
		Iterator<String> it = viewNameMap.keySet().iterator();
		while (it.hasNext() && isAllModelLoaded) {
			isAllModelLoaded = isAllModelLoaded
					&& (viewB.getModel(it.next()) != null);
		}

		if (isAllModelLoaded) {
			RootTemplate rootView = (RootTemplate) controller
					.getView(ROOT_TEMPLATE);
			rootView.changeWidgetB(viewB);

		}
	}

	private class B_ModelLoadHandler implements ModelLoadHandler<Object> {

		ViewB view = null;
		Controller controller = null;
		String modelName = null;

		public B_ModelLoadHandler(ViewB view, Controller controller,
				String modelName) {
			this.view = view;
			this.controller = controller;
			this.modelName = modelName;
		}

		@Override
		public void finishedLoad(ModelLoadEvent<Object> event) {
			view.setModel(modelName, event.getModel());
			handlerRegistrationMap.get(modelName).removeHandler();
			handlerRegistrationMap.remove(modelName);
			displayWidgetB(view, controller);
		}

	}

}
